<template>
  <ContentContainer
    :show-pagination="false"
    :show-footer="false"
    :refresh="false">
    <a-form
      ref="formRef"
      :model="form"
      :rules="rules"
      class="auth-form"
      layout="vertical"
      scroll-to-first-error>
      <div class="weight-label">
        鉴权配置<span
          class="text-xs/5 font-400 text-primary ml-2 cursor-pointer"
          @click="open"
          >功能说明</span
        >
      </div>
      <a-form-item
        field="authorization.status"
        hide-asterisk
        hide-label
        required
        class="normal-leading">
        <a-radio-group v-model="form.authorization.status">
          <a-radio :value="2">关闭</a-radio>
          <a-radio :value="1">开启</a-radio>
        </a-radio-group>
      </a-form-item>
      <section v-if="form.authorization.status === 1">
        <a-form-item
          field="authorization.type"
          hide-asterisk
          label="鉴权模式"
          class="!mb-2"
          required>
          <a-radio-group
            v-model="form.authorization.type"
            @change="handleTypeChange">
            <a-radio
              v-for="item in modeOptions"
              :key="item.value"
              :value="item.value"
              >{{ item.label }}</a-radio
            >
          </a-radio-group>
        </a-form-item>
        <div class="mode-class">
          <div class="normal-label">模式示例</div>
          <div class="text-sm/22px text-4 mb-6 mt-2">
            {{ link[form.authorization.type - 1] }}
          </div>
          <a-form-item field="authorization.secret_key" hide-asterisk required>
            <template #label>
              <section class="flex items-center justify-between w-100">
                <div class="normal-label !mb-0">鉴权密钥</div>
                <div
                  class="normal-label !text-primary cursor-pointer select-none"
                  @click="handleRandomKey">
                  随机生成
                </div>
              </section>
            </template>
            <a-textarea
              v-model.trim="form.authorization.secret_key"
              auto-size
              :max-length="128"
              placeholder="请输入6-128位大小写字母、数字构成的密钥"
              class="!w-100"></a-textarea>
          </a-form-item>
          <a-form-item
            v-if="[1, 4].includes(form.authorization.type)"
            field="authorization.signature_parameter"
            label="签名参数"
            hide-asterisk
            required>
            <a-input
              v-model.trim="form.authorization.signature_parameter"
              placeholder="请输入1-40位签名参数，不能以数字开头"
              :max-length="40"
              class="!w-100"></a-input>
          </a-form-item>
          <a-form-item
            v-if="form.authorization.type === 4"
            field="authorization.timestamp_parameter"
            label="时间戳参数名"
            hide-asterisk
            required>
            <a-input
              v-model.trim="form.authorization.timestamp_parameter"
              :max-length="40"
              placeholder="请输入1-40位时间戳参数名"
              class="!w-100"></a-input>
          </a-form-item>
          <a-form-item
            field="authorization.ttl"
            label="有效时间"
            hide-asterisk
            asterisk-position="end"
            required>
            <section class="w-100 cloud-input-number">
              <a-input-number
                v-model="form.authorization.ttl!"
                :precision="0"
                :min="1"
                :max="630720000"
                :default-value="10"
                placeholder="请输入有效时间">
                <template #append> 秒 </template>
              </a-input-number>
            </section>
          </a-form-item>
          <a-form-item
            label="时间格式"
            field="authorization.timestamp_format"
            class="mb-6"
            hide-asterisk
            :required="
              [1, 2, 3].includes(form.authorization.type) ? false : true
            ">
            <section
              v-if="[1, 2, 3].includes(form.authorization.type)"
              class="text-4 text-sm/22px">
              {{ getOptionsLabel(timeOptions, form.authorization.type) }}
            </section>
            <a-radio-group v-else v-model="form.authorization.timestamp_format">
              <a-radio
                v-for="item in [
                  { value: 10, label: '十进制（Unix时间戳）' },
                  { value: 16, label: '十六进制（Unix时间戳）' }
                ]"
                :key="item.value"
                :value="item.value">
                {{ item.label }}
              </a-radio>
            </a-radio-group>
          </a-form-item>
        </div>
        <a-form-item
          field="authorization.scope"
          label="鉴权范围"
          hide-asterisk
          asterisk-position="end"
          required>
          <a-radio-group v-model="form.authorization.scope">
            <a-radio :value="1">所有文件</a-radio>
            <a-radio :value="2">指定文件后缀鉴权</a-radio>
            <a-radio :value="3">指定文件后缀不鉴权</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item
          v-if="[2, 3].includes(form.authorization.scope)"
          field="authorization.file_extension"
          label="文件后缀"
          hide-asterisk
          required>
          <basic-textarea
            v-model:value.trim="form.authorization.file_extension"
            placeholder="请输入文件后缀，多个值用英文逗号隔开，区分大小写"
            :autoSize="true"></basic-textarea>
        </a-form-item>
      </section>
    </a-form>
    <div class="my-6">
      <a-button
        type="primary"
        class="w-fit"
        :loading="saveLoading"
        @click="handleSave"
        >保存配置</a-button
      >
    </div>
    <FunctionDescriptionDrawer v-model:visible="visible" />
  </ContentContainer>
</template>
<script lang="ts" setup>
import {
  getApiSiteAuthorizationApi,
  updateApiSiteAuthorizationApi
} from '@/apis/modules/site/site'
import { cloneDeep, pick } from 'lodash-es'
import FunctionDescriptionDrawer from './FunctionDescriptionDrawer.vue'
import { timeOptions, modeOptions, type_enum, typeInfo } from '../state'
const route = useRoute()
const id = computed(() => route.params.id as string)
const { visible, open } = usePopup()
const formRef = ref()
const form = ref({
  authorization: {
    status: 2,
    type: 1,
    secret_key: '',
    signature_parameter: '',
    ttl: 10,
    timestamp_parameter: '',
    timestamp_format: 10,
    scope: 1,
    file_extension: '',
    file_suffix_list: []
  }
})

const rules = {
  'authorization.secret_key': [
    {
      required: true,
      minLength: 6,
      maxLength: 128,
      match: /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d]+$/,
      message: '请输入6-128位大小写字母、数字构成的密钥'
    }
  ],
  'authorization.signature_parameter': [
    {
      required: true,
      minLength: 1,
      maxLength: 40,
      message: '请输入签名参数'
    },
    {
      validator: (value, callback) => {
        if (!value) return callback('请输入签名参数')
        const reg = /^(?![0-9])[a-zA-Z0-9_]*$/
        if (!reg.test(value)) {
          callback('请输入大小写字母、数字、下划线（不能以数字开头）')
        }
      }
    }
  ],
  'authorization.ttl': [{ required: true, message: '请输入有效时间' }],
  'authorization.timestamp_parameter': [
    {
      required: true,
      minLength: 1,
      maxLength: 40,
      // match: /^[a-zA-Z0-9_]+$/,
      message: '请输入时间戳参数名'
    },
    {
      validator: (value, callback) => {
        if (!value) return callback('请输入时间戳参数名')
        const reg = /^(?![0-9])[a-zA-Z0-9_]*$/
        if (!reg.test(value)) {
          callback('请输入大小写字母、数字、下划线（不能以数字开头）')
        }
      }
    }
  ],
  'authorization.file_extension': [
    { required: true, message: '请输入文件后缀' },
    {
      validator: validateSuffix
    }
  ]
}

function handleRandomKey() {
  const randomString = generateRandomThreeTypesString(6, 128, false)
  form.value.authorization.secret_key = randomString
  //触发表单校验
  formRef.value?.validateField(['authorization.secret_key'])
}
const link = ref([
  'http://DomainName/Filename?sign=timestamp-rand-md5hash',
  'http://DomainName/timestamp/md5hash/Filename',
  'http://DomainName/md5hash/timestamp/Filename',
  'http://DomainName/Filename?sign=md5hash&time=timestamp'
])

const handleTypeChange = (val: number) => {
  Object.assign(form.value.authorization, typeInfo.value[type_enum[val]])
  form.value.authorization.file_extension =
    typeInfo.value[type_enum[val]]?.file_suffix_list?.join(',') || ''
  formRef.value?.clearValidate()
}
//缓存配置
const { request } = useRequest(getApiSiteAuthorizationApi, {
  auto: false,
  params: { id: id.value },
  success: (res) => {
    Object.assign(form.value, res)
    typeInfo.value = Object.freeze(
      pick(res?.authorization, ['type_a', 'type_b', 'type_c', 'type_d'])
    )
    if (!res?.authorization?.type) form.value.authorization.type = 1
    if (res?.authorization?.type === 1) {
      Object.assign(form.value.authorization, res.authorization.type_a)
    } else if ([2, 3].includes(res?.authorization?.type)) {
      const info =
        res?.authorization?.type === 2
          ? res?.authorization?.type_b
          : res?.authorization?.type_c
      Object.assign(form.value.authorization, info)
    } else {
      Object.assign(form.value.authorization, res?.authorization?.type_d)
    }
    if (form.value.authorization.scope === 1)
      return (form.value.authorization.file_extension = '')
    form.value.authorization.file_extension =
      form.value.authorization?.file_suffix_list?.join(',') || ''
  }
})
const saveLoading = ref(false)
const handleSave = async () => {
  const err = await formRef.value?.validate()
  if (err) return
  saveLoading.value = true
  const data = {
    file_suffix_list: '',
    authorization: {
      type_a: {},
      type_b: {},
      type_c: {},
      type_d: {}
    }
  } as any
  data.authorization = cloneDeep(form.value.authorization)
  data.id = id.value
  const type = form.value.authorization.type
  const {
    authorization: { file_extension }
  } = form.value
  if (type === 1) {
    Object.assign(
      data.authorization.type_a,
      pick(data.authorization, [
        'scope',
        'secret_key',
        'signature_parameter',
        'ttl'
      ])
    )
    data.authorization.type_a.file_suffix_list = file_extension
      ? file_extension.split(',')
      : []
  } else if (type === 2) {
    Object.assign(
      data.authorization.type_b,
      pick(data.authorization, ['scope', 'secret_key', 'ttl'])
    )
    data.authorization.type_b.file_suffix_list = file_extension
      ? file_extension.split(',')
      : []
  } else if (type === 3) {
    Object.assign(
      data.authorization.type_c,
      pick(data.authorization, ['scope', 'secret_key', 'ttl'])
    )
    data.authorization.type_c.file_suffix_list = file_extension
      ? file_extension.split(',')
      : []
  } else {
    Object.assign(
      data.authorization.type_d,
      pick(data.authorization, [
        'scope',
        'secret_key',
        'signature_parameter',
        'timestamp_parameter',
        'timestamp_format',
        'ttl'
      ])
    )
    data.authorization.type_d.file_suffix_list = file_extension
      ? file_extension.split(',')
      : []
  }
  const params = {
    id: id.value,
    authorization: pick(data.authorization, [
      'status',
      'type',
      'type_a',
      'type_b',
      'type_c',
      'type_d'
    ])
  }

  updateApiSiteAuthorizationApi(params)
    .then(() => {
      ToastUtils.success('操作成功')
      request({ id: id.value })
    })
    .finally(() => (saveLoading.value = false))
}
watchEffect(() => {
  request({ id: id.value })
})
</script>

<style lang="less" scoped>
.weight-label {
  @apply text-sm/22px font-700 text-1 mb-6;
}
.normal-label {
  @apply text-sm/22px text-2;
}
.sub-label {
  @apply text-xs/5 text-5;
}
.mode-class {
  @apply w-full h-fit rounded-2 p-6 mb-6;
  border: 1px dashed #dfe2e5;
}
.auth-form {
  :deep(.arco-form-item-wrapper-col) {
    @apply !min-h-22px;
    .arco-form-item-content {
      @apply !min-h-22px;
      &:has(.arco-radio-group) {
        @apply !min-h-22px;
      }
    }
  }
}
</style>
